#include "tcp_client.h"

#include <iostream>
#include <string>

#ifdef _WIN32_
#include <winsock2.h>
#define write(fd, data, size) send((fd), (data), (size), 0)
#define read(fd, data, size) recv((fd), (data), (size), 0)
#else // Linux
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#define closesocket close
#endif

using Ohscrcpy::TcpClient;

namespace {
const std::string TAG = "TcpClient";
}

bool TcpClient::Init() {
#ifdef _WIN32_
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cout << TAG << ": " << "init failed" << std::endl;
        return false;
    }
#endif
    return true;
}

TcpClient::~TcpClient() {
#ifdef _WIN32_
    WSACleanup();
#endif
}

bool TcpClient::Connect(const char *ip, unsigned short port) {
    std::cout << TAG << ": " << "connect, ip=" << ip << ", port=" << port << std::endl;
    socketFd = socket(AF_INET, SOCK_STREAM, 0);
    if (socketFd == -1) {
        std::cout << TAG << ": " << "create socket failed" << std::endl;
        return false;
    }

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(ip);
    address.sin_port = htons(port);

    if (connect(socketFd, (struct sockaddr *)&address, sizeof(address)) == -1) {
        std::cout << TAG << ": " << "connect failed" << std::endl;
        return false;
    } else {
        return true;
    }
}

int TcpClient::Recv(char *buf, int bufsize) {
    return recv(socketFd, buf, bufsize, MSG_WAITALL);
}

int TcpClient::Send(const char *buf, int size) {
    int s = 0;
    while (s != size) {
        int len = send(socketFd, buf + s, size - s, 0);
        if (len <= 0) {
            break;
        }
        s += len;
    }
    return s;
}

void TcpClient::Close() {
    if (socketFd <= 0) {
        return;
    }
    closesocket(socketFd);
}